package com.bryant.demo05.storage

import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.bryant.demo05.WeatherApplication
import com.google.common.reflect.TypeToken
import com.google.gson.Gson

object FavoriteManager {
    // ---------------------------------- 变量定义 --------------------------------------------------

    // 1. 定义对象存储 - 延迟初始化 -> 非空保证
    private lateinit var sharedPreferences: SharedPreferences

    // 2. 定义SharedPreferences文件的名称
    private const val PREFS_NAME = "city_favorite_prefs"

    // 3. 定义用于存储收藏城市的键名
    private const val FAVORITE_PREFIX = "favorites_"

    // 4. 初始化Gson对象用于JSON序列化和反序列化
    private val gson = Gson()

    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


    // -----------------------------------方法定义--------------------------------------------------
    //1. 初始化
   fun  init(context: Context) {
       // 初始化对象存储
       sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
   }

    // 2. 定义获取用户名方法 - 可能为空
    private fun getCurrentUserKey (): String? {
        val userKey = WeatherApplication.user.username
        return "$FAVORITE_PREFIX$userKey"
    }

    // 3. 定义一系列收藏列表方法

    // 3.1 添加数据
    fun addFavorite(cityData: CityData) {
        // 1. 获取key
        val userKey = getCurrentUserKey() ?: return
        // 2. 获取收藏列表 - toMutableSet()作用是创建一个可变集合，这样我们可以在原集合上进行修改。
        val currentSet = getFavoritesForUser(userKey).toMutableSet()
        // 3. 先移除
        currentSet.remove(cityData)
        // 4. 添加
        currentSet.add(cityData)
        // 5. 存储数据
        saveFavoritesForUser(userKey, currentSet)
    }

    // 3.2 删除数据
    fun removeFavorite(cityName: String) {
        val userKey = getCurrentUserKey() ?: return
        val currentSet = getFavoritesForUser(userKey).toMutableSet()
        val tempCity = CityData(cityName, 0.0, 0.0, "", "")
        currentSet.remove(tempCity)
        saveFavoritesForUser(userKey, currentSet)
    }
    // 3.3 切换
    fun toggleFavorite(cityData: CityData): Boolean {
        val userKey = getCurrentUserKey() ?: return false
        val currentSet = getFavoritesForUser(userKey).toMutableSet()
        val tempCity = CityData(cityData.name, 0.0, 0.0, "", "")
        val isFavorite = currentSet.contains(tempCity)

        if (isFavorite) {
            currentSet.remove(tempCity)
        } else {
            currentSet.add(cityData)
        }

        saveFavoritesForUser(userKey, currentSet)
        return !isFavorite
    }

    // 3.4 获取数据 - 返回一个CityData类型的集合 - 且不重复 -> 用set
    fun getCurrentUserFavorites () : Set<CityData>{
        // 1. 先获取key
        val userKey = getCurrentUserKey() ?: return emptySet()
        return getFavoritesForUser(userKey)
    }

    // 3.5 检查城市是否在收藏列表中
    fun isFavorite(cityName: String): Boolean {
        val userKey = getCurrentUserKey() ?: return false
        val tempCity = CityData(cityName, 0.0, 0.0, "", "")
        return getFavoritesForUser(userKey).contains(tempCity)
    }

    // 4. 根据username获取收藏列表 - 并用gson进行序列化
    private fun getFavoritesForUser(userKey: String): Set<CityData> {
        // 1. 从SharedPreferences获取原始字符串集合 JSON格式字符串
        //第二个参数的作用：这是 SharedPreferences 的默认值参数。
        // 当通过 userKey 在 sharedPreferences 中找不到对应的数据时，会返回这个默认值。
        val jsonSet = sharedPreferences.getStringSet(userKey,  mutableSetOf()) ?: return emptySet()
        return try {
            if (jsonSet.isEmpty()){
                emptySet()
            }else{
                //作用是使用 Gson 将存储在 SharedPreferences 中的 JSON 字符串集合反序列化为 Set<CityData> 对象集合。
                // 使用TypeToken获取目标类型信息
                val type = object : TypeToken<Set<CityData>>() {}.type
                // 使用Gson将字符串转换为CityData对象集合
                gson.fromJson(jsonSet.toString(), type) ?: emptySet()
            }
        }catch (e: Exception){
            emptySet()
        }
    }
    // 5. 存储数据
    private fun saveFavoritesForUser(userKey: String, cities: Set<CityData>) {
        // 将CityData对象集合转换为JSON字符串集合
        val jsonSet = cities.map { gson.toJson(it) }.toSet()
        // 使用SharedPreferences编辑器保存数据
        sharedPreferences.edit {
            putStringSet(userKey, jsonSet)
            apply()
        }
    }

    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

}